#include<unistd.h>
#include<string.h>
#include<semaphore.h>
#include<pthread.h>
#include<iostream>

class Sem
{
    public:
    Sem(int num)
    {
        sem_init(&sem,0,num);
    }
    void V()
    {
        sem_wait(&sem);
    }
    void P()
    {
        sem_post(&sem);
    }
    ~Sem()
    {
        sem_destroy(&sem);
    }
    private:
    sem_t sem;
};
static int num=0;
Sem sem(num);
static int tickets=2000;

void * ThreadRoutine(void*args)
{
    std::string name=static_cast<const char*>(args);
    while(true)

    {
        sem.P();
        if(tickets>0)
        {
            std::cout<<name<<" get a ticket "<<tickets--<<std::endl;
            sem.V();
        }
        else
        {
            std::cout<<"no tickets"<<std::endl;
            sem.V();
            break;
        }
    }
    std::cout << name << " quit..." << std::endl;
    pthread_exit((void*)0);
}
char* GetThreadname()
{
    static int n=1;
    char buffer[64];
    snprintf(buffer,sizeof(buffer),"Thread-%d",n++);
    return buffer;
}
int main()
{
    pthread_t td1,td2,td3;
    char* name1=GetThreadname();
    pthread_create(&td1,nullptr,ThreadRoutine,(void*)name1);
    char* name2=GetThreadname();
    pthread_create(&td2,nullptr,ThreadRoutine,(void*)name2);
    char* name3=GetThreadname();
    pthread_create(&td3,nullptr,ThreadRoutine,(void*)name3);

    pthread_join(td1,nullptr);
    pthread_join(td2,nullptr);
    pthread_join(td3,nullptr);
    return 0;
}